package org.ohos.rajawali3d.examples.views;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.miscservices.timeutility.Time;
import ohos.opengl.Bitmap;
import org.ohos.rajawali3d.ResourceTable;


public class GitHubLogoView extends Component implements Component.DrawTask, Component.EstimateSizeListener {

    protected Canvas mBackgroundCanvas;
    protected PixelMap mBackground;
    protected PixelMap mMask;
    protected Paint mPaint;
    protected Rect mDrawingRect;
    protected boolean mDirection;
    protected long mLastChange;
    protected int mDuration;
    private EventHandler mHandler;

    public GitHubLogoView(Context context) {
        this(context, null);
    }

    public GitHubLogoView(Context context, AttrSet attrs) {
        this(context, attrs, 0);
    }

    public GitHubLogoView(Context context, AttrSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mDuration = 2000;

        mMask = Bitmap.getPixelMapFromResource(getResourceManager(),
                ResourceTable.Media_githublogo);

        mPaint = new Paint();
        mPaint.setColor(new Color(0xffff0000));
        mPaint.setAntiAlias(true);
        setEstimateSizeListener(this);
        mBackgroundCanvas = new Canvas();
        mHandler = new EventHandler(EventRunner.getMainEventRunner());
    }

    protected static PixelMap convertToAlphaMask(PixelMap b) {
        final PixelMap a = Bitmap.create(b.getImageInfo().size.width, b.getImageInfo().size.height,
                PixelFormat.ARGB_8888);
        final Canvas c = new Canvas(new Texture(a));
        c.save();
        c.drawPixelMapHolder(new PixelMapHolder(b), 0.0f, 0.0f, new Paint());
        c.restore();
        return a;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        final long time = Time.getRealActiveTime();
        final int diff = (int) (time - mLastChange);
        if (time - mLastChange > mDuration) {
            mDirection = !mDirection;
            mLastChange = time;
        }

        final float percent = (mDirection ? diff % mDuration : mDuration
                - (diff % mDuration))
                / (float) mDuration;

        int color = (Integer) evaluate(percent, 0xffffffff, 0xffff8800);
        canvas.save();
        mPaint.setColor(new Color(color));

        // Draw the masked logo in the new color
        canvas.drawRect(mDrawingRect, mPaint);


        // Draw the new logo
        canvas.drawPixelMapHolder(new PixelMapHolder(mBackground), 0, 0, mPaint);
        canvas.restore();
        startDrawing();
    }

    @Override
    public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
        int w = EstimateSpec.getSize(widthEstimateConfig);
        int h = EstimateSpec.getSize(heightEstimateConfig);
        mDrawingRect = new Rect(0, 0, w, h);

        final PixelMap mask = convertToAlphaMask(Bitmap.createScaledBitmap(mMask,
                w, h, false));
        mPaint.setShader(new PixelMapShader(new PixelMapHolder(mask), Shader.TileMode.CLAMP_TILEMODE,
                Shader.TileMode.CLAMP_TILEMODE), Paint.ShaderType.PIXELMAP_SHADER);

        mBackground = Bitmap.create(w, h, PixelFormat.ARGB_8888);
        mBackgroundCanvas.setTexture(new Texture(mBackground));
        return false;
    }

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        float startA = ((startInt >> 24) & 0xff) / 255.0f;
        float startR = ((startInt >> 16) & 0xff) / 255.0f;
        float startG = ((startInt >> 8) & 0xff) / 255.0f;
        float startB = (startInt & 0xff) / 255.0f;

        int endInt = (Integer) endValue;
        float endA = ((endInt >> 24) & 0xff) / 255.0f;
        float endR = ((endInt >> 16) & 0xff) / 255.0f;
        float endG = ((endInt >> 8) & 0xff) / 255.0f;
        float endB = (endInt & 0xff) / 255.0f;

        // convert from sRGB to linear
        startR = (float) Math.pow(startR, 2.2);
        startG = (float) Math.pow(startG, 2.2);
        startB = (float) Math.pow(startB, 2.2);

        endR = (float) Math.pow(endR, 2.2);
        endG = (float) Math.pow(endG, 2.2);
        endB = (float) Math.pow(endB, 2.2);

        // compute the interpolated color in linear space
        float a = startA + fraction * (endA - startA);
        float r = startR + fraction * (endR - startR);
        float g = startG + fraction * (endG - startG);
        float b = startB + fraction * (endB - startB);

        // convert back to sRGB in the [0..255] range
        a = a * 255.0f;
        r = (float) Math.pow(r, 1.0 / 2.2) * 255.0f;
        g = (float) Math.pow(g, 1.0 / 2.2) * 255.0f;
        b = (float) Math.pow(b, 1.0 / 2.2) * 255.0f;

        return Math.round(a) << 24 | Math.round(r) << 16 | Math.round(g) << 8 | Math.round(b);
    }

    public void startDrawing() {
        mHandler.postTask(new Runnable() {
            @Override
            public void run() {
                addDrawTask(GitHubLogoView.this);
            }
        }, 1000);
    }
}
